﻿#include "../encoding/utf8.h"
#include "wait.h"
#include "event.h"

namespace nsshare
{
namespace sys
{

Event::Event()
    : handle_(0)
{

}

Event::~Event()
{
    fini();
}

//auto reset, initial = unsignal
bool Event::init()
{
    return init(false);
}

//initial = unsignal
bool Event::init(bool manual_reset)
{
    return init(manual_reset, false);
}

bool Event::init(bool manual_reset, bool initial_state)
{
    if(handle_)
        return true;

    handle_ = CreateEvent(0, manual_reset, initial_state, 0);
    if (handle_ == NULL)
        return false;

    return true;
}

void Event::fini()
{
    if(handle_)
    {
        CloseHandle(handle_);
        handle_ = 0;
    }
}

bool Event::Set()
{
    if(handle_ == NULL)
        return false;

    if (!SetEvent(handle_))
        return false;

    return true;
}

bool Event::Reset()
{
    if(handle_ == NULL)
        return false;

    if (!ResetEvent(handle_))
        return false;
         
    return true;
}

bool Event::Wait(uint32_t timeout)
{
    return WaitEx(timeout, false);
}

bool Event::WaitEx(uint32_t timeout, bool alertable)
{
    return Wait::WaitOne(*this, timeout, alertable);
}

void * Event::WaitableHandle() const
{
    return handle_;
}

//NamedEvent
NamedEvent::NamedEvent()
    : handle_(0)
{
}

NamedEvent::~NamedEvent()
{
    Close();
}

bool NamedEvent::Create(bool manual_reset, 
                        bool initial_state, 
                        const char * name)
{
    if(!name)
        return false;
    if(handle_)
        return true;

    wchar_t name16[260] = {0};
    encoding::UTF8::Decode(name, -1, name16, 260);

    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = FALSE;

    handle_ = CreateEvent(&sa, manual_reset, initial_state, name16);
    if (handle_ == NULL)
        return false;

    return true;
}

bool NamedEvent::Open(const char * name)
{
    if(handle_)
        return true;

    wchar_t name16[260] = {0};
    encoding::UTF8::Decode(name, -1, name16, 260);

    DWORD access = EVENT_MODIFY_STATE | SYNCHRONIZE;
    handle_ = OpenEvent(access, FALSE, name16);
    if (handle_ == NULL)
        return false;
    return true;
}

void NamedEvent::Close()
{
    if(handle_)
    {
        CloseHandle(handle_);
        handle_ = 0;
    }
}

bool NamedEvent::Set()
{
    if(handle_ == NULL)
        return false;

    if (!SetEvent(handle_))
        return false;

    return true;
}

bool NamedEvent::Reset()
{
    if(handle_ == NULL)
        return false;

    if (!ResetEvent(handle_))
        return false;
         
    return true;
}

bool NamedEvent::Wait(uint32_t timeout)
{
    return WaitEx(timeout, false);
}

bool NamedEvent::WaitEx(uint32_t timeout, bool alertable)
{
    return Wait::WaitOne(*this, timeout, alertable);
}

void * NamedEvent::WaitableHandle() const
{
    return handle_;
}

bool NamedEvent::IsPremier()
{
    return ERROR_ALREADY_EXISTS != GetLastError();
}

}
}

